package com.sunxd.zstudy.mybatise.domain.service.engine.handler.join.lottery;

import com.sunxd.zstudy.mybatise.domain.contans.enums.PrizeIssueType;
import com.sunxd.zstudy.mybatise.domain.contans.enums.RewardType;
import com.sunxd.zstudy.mybatise.domain.dto.InteractiveReward;
import com.sunxd.zstudy.mybatise.domain.dto.InteractiveRewardDetail;
import com.sunxd.zstudy.mybatise.domain.dto.LotteryReward;
import com.sunxd.zstudy.mybatise.infrastructure.utils.RandomUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Component
@AllArgsConstructor
public class ProbabilityIssueProcessor implements IssueProcessor {

    private final RandomUtils randomUtils;

    @Override
    public String getIssueType() {
        return PrizeIssueType.PROBABILITY.name();
    }

    @Override
    public LotteryReward lottery(InteractiveReward interactiveReward) {
        BigDecimal random = randomUtils.random();
        List<InteractiveRewardDetail> interactiveRewardDetails = interactiveReward.getInteractiveRewardDetails();
        interactiveRewardDetails = interactiveRewardDetails.stream().sorted(Comparator.comparing(InteractiveRewardDetail::getRightNum)).collect(Collectors.toList());
        InteractiveRewardDetail thanksPrize = interactiveRewardDetails.stream()
                .filter(x -> Objects.equals(x.getRewardType(), RewardType.THANKS.name()))
                .findAny()
                .orElse(null);
        LotteryReward lotteryPrize = LotteryReward.builder()
                .thanks(thanksPrize)
                .build();
        InteractiveRewardDetail interactiveRewardDetail = searchPrize(interactiveRewardDetails.toArray(new InteractiveRewardDetail[0]), random.doubleValue());
        if(Objects.isNull(interactiveRewardDetail)){
            return lotteryPrize;
        }
        // todo 单个奖品中将以后的限制
        lotteryPrize.setReward(interactiveRewardDetail);
        return lotteryPrize;

    }

    private static InteractiveRewardDetail searchPrize(InteractiveRewardDetail[] rewardDetails, double random) {

        if (rewardDetails.length == 1) {
            return rewardDetails[0];
        }
        int index = binarySearch(rewardDetails, 0, rewardDetails.length - 1, random);
        log.info("当前抽中的奖品的索引:{}，random：{}",index,random);
        if (index != -1) {
            return rewardDetails[index];
        }
        return null;
    }

    public static int binarySearch(InteractiveRewardDetail[] prizeInCaches, int low, int high, double random) {
        int mid;
        while (low <= high) {
            mid = (low + high) / 2;

            if (prizeInCaches[mid].getRightNum() > random) {
                high = mid - 1;
                if (high < 0) {
                    return mid;
                }
            } else if (prizeInCaches[mid].getRightNum() < random) {
                low = mid + 1;
            } else {
                return mid;
            }
        }
        //待查找的数比最大的数还要大,或者比最小的数还要小
        if (low > prizeInCaches.length - 1 || high < 0) {
            return -1;
        }
        return low;
    }
}
